package obecto.utility
{	
	import flash.utils.describeType;
	import flash.utils.getQualifiedClassName;
	
	/**
	 * @author Todor Kolev
	 */
	public class AssertionUtil 
	{
		/*
		private static function logAssertion(
			aLogLevel : Level, 
			aMessage : String, 
			aContextObject : Object, aContextMethodArguments : Array) : void
		{
			var logger : Logger = Logger.getLoggerFor(aContextObject);	
			
			var contextString : String = getCallContextString(aContextObject, aContextMethodArguments);
		
			var logString : String = aMessage + " [" + contextString + "]";
			
			logger.log(aLogLevel, logString);
		}
		
		private static function getCallContextString(aContextObject : Object, aCallArguments : Array) : String
		{
			var argumentsArray : Array = aCallArguments;
			var argumentsString : String = CollectionUtility.arrayToString(argumentsArray);
			
			var contextMethod : Function = aCallArguments.callee;		
			
			var typeInfo : String = getQualifiedClassName(aContextObject);
			var methodName : String = getMethodName(aContextObject, contextMethod); // getQualifiedClassName(contextMethod)
	
			var contextString : String;
			contextString = typeInfo + "."  + methodName + "(" + argumentsString + ")";
			
			return contextString;
		}
		
		private static function getMethodName(aContext : Object, aMethod : Function) : String
		{
			var contextDescription : XML = describeType(aContext);
				
			for each (var methodInfo : XML in contextDescription..method) 
			{
                var methodName : String = methodInfo.@name;
                
                if(aContext[methodName] == aMethod)
                {
                	return methodName;
                }
            }
            
            return "function";
		}
		
		private static function evaluateMethod(aScope:Object, aMethod:Function, aArguments:Array) : Object
		{
			if(aArguments == null)
			{
				aArguments = new Array();
			}
			
			return aMethod.apply(aScope, aArguments);
		}
		
		public static function fail(aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			logAssertion(Level.SEVERE, aMessage, aContextObject, aContextMethodArguments);
			throw new Error(aMessage);
		}
		
		public static function failIfTrue(aVar:Boolean, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(aVar)
			{
				fail(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function failIfFalse(aVar:Boolean, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(!aVar)
			{
				fail(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function failIfNotNull(aVar:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(aVar !== null)
			{
				fail(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function failIfNull(aVar:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(aVar === null)
			{
				fail(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function failIfUndefined(aVar:*, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(aVar === undefined)
			{
				fail(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function failIfNotUndefined(aVar:*, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(aVar !== undefined)
			{
				fail(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function failIfNullOrUndefined(aVar:*, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(aVar === null && aVar === undefined)
			{
				fail(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function failIfEmpty(aVar:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(aVar == null || aVar == "")
			{
				fail(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function failIfNotEqual(aVar1:Object, aVar2:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(aVar1 != aVar2)
			{
				fail(aMessage + "(" + aVar1 + " != " + aVar2 + ")", aContextObject, aContextMethodArguments);
			}
		}
		
		public static function failIfNotSame(aVar1:Object, aVar2:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(aVar1 !== aVar2)
			{
				fail(aMessage + "(" + aVar1 + " !== " + aVar2 + ")", aContextObject, aContextMethodArguments);
			}
		}
	
		public static function failIfNotInstanceOf(aVar:Object, aType:Class, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(!(aVar is aType))
			{
				fail(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function failIfReturns(aScope:Object, aMethod:Function, aArguments:Array, aReturnValue:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(evaluateMethod(aScope, aMethod, aArguments) === aReturnValue)
			{
				fail(aMessage, aContextObject, aContextMethodArguments);
			}
		}
	
		public static function failIfReturnsTrue(aScope:Object, aMethod:Function, aArguments:Array, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			failIfReturns(aScope, aMethod, aArguments, true, aMessage, aContextObject, aContextMethodArguments);
		}
	
		public static function failIfReturnsFalse(aScope:Object, aMethod:Function, aArguments:Array, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			failIfReturns(aScope, aMethod, aArguments, false, aMessage, aContextObject, aContextMethodArguments);
		}
		
		public static function failIfReturnsNull(aScope:Object, aMethod:Function, aArguments:Array, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			var methodResult : Object = evaluateMethod(aScope, aMethod, aArguments);
			if(methodResult === null)
			{
				fail(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function failIfReturnsNotNull(aScope:Object, aMethod:Function, aArguments:Array, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			var methodResult : Object = evaluateMethod(aScope, aMethod, aArguments);
			if(methodResult !== null)
			{
				fail(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function failIfContainsValue(aCollection:Object, aValue:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(CollectionUtility.containsValue(aCollection, aValue))
			{
				fail(aMessage, aContextObject, aContextMethodArguments);
			}
		}
	
		public static function failIfContainsKey(aCollection:Object, aKey:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(CollectionUtility.containsKey(aCollection, aKey))
			{
				fail(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function failIfNotContainsValue(aCollection:Object, aValue:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(!CollectionUtility.containsValue(aCollection, aValue))
			{
				fail(aMessage, aContextObject, aContextMethodArguments);
			}
		}
	
		public static function failIfNotContainsKey(aCollection:Object, aKey:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(!CollectionUtility.containsKey(aCollection, aKey))
			{
				fail(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function warning(aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			logAssertion(Level.WARNING, aMessage, aContextObject, aContextMethodArguments);
		}
		
		public static function warningIfTrue(aVar:Boolean, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(aVar)
			{
				warning(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function warningIfFalse(aVar:Boolean, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(!aVar)
			{
				warning(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function warningIfNotNull(aVar:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(aVar != null)
			{
				warning(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function warningIfNull(aVar:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(aVar == null)
			{
				warning(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		public static function warningIfUndefined(aVar:*, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(aVar === undefined)
			{
				warning(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function warningIfNotUndefined(aVar:*, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(aVar !== undefined)
			{
				warning(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function warningIfNullOrUndefined(aVar:*, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(aVar === null && aVar === undefined)
			{
				fail(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function warningIfEmpty(aVar:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(aVar == null || aVar == "")
			{
				warning(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function warningIfNotEqual(aVar1:Object, aVar2:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(aVar1 != aVar2)
			{
				warning(aMessage + "(" + aVar1 + " != " + aVar2 + ")", aContextObject, aContextMethodArguments);
			}
		}
		
		public static function warningIfNotSame(aVar1:Object, aVar2:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(aVar1 !== aVar2)
			{
				warning(aMessage + "(" + aVar1 + " !== " + aVar2 + ")", aContextObject, aContextMethodArguments);
			}
		}
		
		public static function warningIfNotInstanceOf(aVar:Object, aType:Class, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(!(aVar is aType))
			{
				warning(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function warningIfReturns(aScope:Object, aMethod:Function, aArguments:Array, aReturnValue:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(evaluateMethod(aScope, aMethod, aArguments) === aReturnValue)
			{
				warning(aMessage, aContextObject, aContextMethodArguments);
			}
		}
	
		public static function warningIfReturnsTrue(aScope:Object, aMethod:Function, aArguments:Array, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			warningIfReturns(aScope, aMethod, aArguments, true, aMessage, aContextObject, aContextMethodArguments);
		}
	
		public static function warningIfReturnsFalse(aScope:Object, aMethod:Function, aArguments:Array, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			warningIfReturns(aScope, aMethod, aArguments, false, aMessage, aContextObject, aContextMethodArguments);
		}
		
		public static function warningIfReturnsNull(aScope:Object, aMethod:Function, aArguments:Array, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			var methodResult : Object = evaluateMethod(aScope, aMethod, aArguments);
			if(methodResult === null)
			{
				warning(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function warningIfReturnsNotNull(aScope:Object, aMethod:Function, aArguments:Array, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			var methodResult : Object = evaluateMethod(aScope, aMethod, aArguments);
			if(methodResult !== null)
			{
				warning(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function warningIfContainsValue(aCollection:Object, aValue:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(CollectionUtility.containsValue(aCollection, aValue))
			{
				warning(aMessage, aContextObject, aContextMethodArguments);
			}
		}
	
		public static function warningIfContainsKey(aCollection:Object, aKey:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(CollectionUtility.containsKey(aCollection, aKey))
			{
				warning(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		
		public static function warningIfNotContainsValue(aCollection:Object, aValue:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(!CollectionUtility.containsValue(aCollection, aValue))
			{
				warning(aMessage, aContextObject, aContextMethodArguments);
			}
		}
	
		public static function warningIfNotContainsKey(aCollection:Object, aKey:Object, aMessage:String, aContextObject:Object, aContextMethodArguments:Array) : void
		{
			if(!CollectionUtility.containsKey(aCollection, aKey))
			{
				warning(aMessage, aContextObject, aContextMethodArguments);
			}
		}
		*/
		
		public static function disableLogging() : void
		{ 
			/*Assertion.fail = null;
			Assertion.failIfEmpty = null;
			Assertion.failIfFalse = null;
			Assertion.failIfNotEqual = null;
			Assertion.failIfNotNull = null;
			Assertion.failIfNotSame = null;
			Assertion.failIfNull = null;
			Assertion.failIfTrue = null;
			Assertion.failIfNotInstanceOf = null;
			Assertion.failIfReturns = null;
			Assertion.warningIfReturnsFalse = null;
			Assertion.failIfReturnsTrue = null;
			Assertion.failIfReturnsNull = null;
			Assertion.failIfReturnsNotNull = null;
			Assertion.failIfContainsKey = null;
			Assertion.failIfContainsValue = null;
			Assertion.failIfNotContainsKey = null;
			Assertion.failIfNotContainsValue = null;
	
			Assertion.warning = null;
			Assertion.warningIfEmpty = null;
			Assertion.warningIfFalse = null;
			Assertion.warningIfNotEqual = null;
			Assertion.warningIfNotNull = null;
			Assertion.warningIfNotSame = null;
			Assertion.warningIfNull = null;
			Assertion.warningIfTrue = null;
			Assertion.failIfNotInstanceOf = null;
			Assertion.failIfReturns = null;
			Assertion.warningIfReturnsFalse = null;
			Assertion.warningIfReturnsTrue = null;
			Assertion.warningIfReturnsNull = null;
			Assertion.warningIfReturnsNotNull = null;
			Assertion.warningIfContainsKey = null;
			Assertion.warningIfContainsValue = null;
			Assertion.warningIfNotContainsKey = null;
			Assertion.warningIfNotContainsValue = null;*/
		}
	}
}